package com.atguigu.gulimall.ware.service.impl;

import com.atguigu.common.constant.WareConstant;
import com.atguigu.gulimall.ware.entity.PurchaseDetailEntity;
import com.atguigu.gulimall.ware.service.PurchaseDetailService;
import com.atguigu.gulimall.ware.service.WareSkuService;
import com.atguigu.gulimall.ware.vo.MergeVO;
import com.atguigu.gulimall.ware.vo.PurchaseDoneVO;
import com.atguigu.gulimall.ware.vo.PurchaseItemDoneVO;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atguigu.common.utils.PageUtils;
import com.atguigu.common.utils.Query;

import com.atguigu.gulimall.ware.dao.PurchaseDao;
import com.atguigu.gulimall.ware.entity.PurchaseEntity;
import com.atguigu.gulimall.ware.service.PurchaseService;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;


@Service("purchaseService")
public class PurchaseServiceImpl extends ServiceImpl<PurchaseDao, PurchaseEntity> implements PurchaseService {
    @Resource
    private PurchaseDetailService detailService;
    @Resource
    private WareSkuService wareSkuService;

    /*查询*/
    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<PurchaseEntity> page = this.page(
                new Query<PurchaseEntity>().getPage(params),
                new QueryWrapper<PurchaseEntity>()
        );

        return new PageUtils(page);
    }

    /**
     * 查询未领取的采购单
     */
    @Override
    public PageUtils queryPageUnreceivePurchase(Map<String, Object> params) {
        // 采购状态必须是0或1,0是新建,1是已分配,只要是0,1表示这个采购单还没有被采购人领取出发
        IPage<PurchaseEntity> page = this.page(
                new Query<PurchaseEntity>().getPage(params),
                new QueryWrapper<PurchaseEntity>().eq("status", 0).or().eq("status", 1)
        );
        return new PageUtils(page);
    }


    /*新增*/

    /**
     * 合并采购需求为一个采购单
     */
    @Transactional
    @Override
    public void mergePurchase(MergeVO mergeVO) {
        // 如果有采购单的id,那么就合并到这个采购单里面,没有的话那么就新建一个采购单,合并到这个新采购单上面
        Long purchaseId = mergeVO.getPurchaseId();
        if (purchaseId == null) {
            // 新建采购单
            PurchaseEntity purchaseEntity = new PurchaseEntity();

            purchaseEntity.setStatus(WareConstant.PurchaseStatusEnum.CREATED.getCode());// 默认采购单状态为0，就是新建
            purchaseEntity.setCreateTime(new Date());
            purchaseEntity.setUpdateTime(new Date());
            this.save(purchaseEntity);
            purchaseId = purchaseEntity.getId();// 数据库自增,所以会给他自动分配id，不用担心

            // 无论purchaseId是否为空都需要合并采购需求到这个采购单里面,所以下面的操作时两种情况共有的操作我们写到if外面
        }
        /**
         * 否则合并到这个指定的采购单里面
         * 合并就是修改,修改wms_purchase_detail采购需求里面:
         *     purchase_id:(采购单id)
         *     status:采购需求的状态(新建变已分配)
         */
        List<Long> items = mergeVO.getItems();// 注:items是一个采购单id的集合(wms_purchase_detail的id主键)
        Long finalPurchaseId = purchaseId;
        List<PurchaseDetailEntity> collect = items.stream().map(i -> {
            PurchaseDetailEntity detailEntity = new PurchaseDetailEntity();
            detailEntity.setId(i);
            detailEntity.setPurchaseId(finalPurchaseId);
            detailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.ASSIGNED.getCode());
            return detailEntity;
        }).collect(Collectors.toList());
        detailService.updateBatchById(collect);

        // 下面是更新时间字段
        PurchaseEntity purchaseEntity = new PurchaseEntity();
        purchaseEntity.setId(purchaseId);
        purchaseEntity.setUpdateTime(new Date());
        this.updateById(purchaseEntity);
    }

    /*删除*/

    /*修改*/

    /**
     * 领取采购单  请求的参数:采购单Id(是个数组)
     * 思路:
     * 前提:当前采购单的状态是新建或已分配
     * 1.当采购人领取了1号采购单,那么他的状态变为已领取
     * 2.该采购单的采购需求的状态变为正在采购
     */
    @Transactional
    @Override
    public void received(List<Long> ids) {
        // 确认当前采购单的状态是新建或已分配
        List<PurchaseEntity> purchaseEntitys = ids.stream().map(this::getById)
                .filter(item -> item.getStatus() == WareConstant.PurchaseStatusEnum.CREATED.getCode() || item.getStatus() == WareConstant.PurchaseStatusEnum.ASSIGNED.getCode())
                .map(item -> {
                    // 将采购单状态设置为已领取
                    item.setStatus(WareConstant.PurchaseStatusEnum.RECEIVE.getCode());
                    item.setUpdateTime(new Date());
                    return item;
                }).collect(Collectors.toList());
        // 1.当采购人领取了1号采购单,那么他的状态变为已领取
        this.updateBatchById(purchaseEntitys);
        // 2.该采购单的采购需求的状态变为正在采购
        purchaseEntitys.forEach(item -> {
            List<PurchaseDetailEntity> entities = detailService.listDetailByPurchaseId(item.getId());
            List<PurchaseDetailEntity> detailEntities = entities.stream().map(entity -> {
                PurchaseDetailEntity entity1 = new PurchaseDetailEntity();
                entity1.setId(entity.getId());
                entity1.setStatus(WareConstant.PurchaseDetailStatusEnum.BUYING.getCode());
                return entity1;
            }).collect(Collectors.toList());
            detailService.updateBatchById(detailEntities);

        });
    }

    /**
     * 完成采购     post:/ware/purchase/done
     * 请求参数:
     * id: 123,//采购单id
     * items: [{itemId:1,status:4,reason:""}] itemId是采购项(采购需求id),status:是采购项的状态(3是已完成,4是采购失败),采购失败说原因
     * 响应结果:
     * "msg": "success",
     * "code": 0
     * 我们有一个页面,展示的是该采购单里面的采购项(采购需求),哪些完成了会被勾中,点一个确认,勾中的就完成了,没完成的要指定没完成的原因
     * 所以我们提交了每一个采购项(采购需求)的状态,勾上了就是采购完成了,没勾上还要提交原因
     */
    @Transactional
    @Override
    public void done(PurchaseDoneVO doneVO) {
        /**
         * 思路
         * 1.改变采购单状态
         *      难点:采购单的状态要跟采购项的状态走,如果所有的采购项都是成功做完的,那么采购单的状态就是已完成
         *           如果有一个采购项的状态是失败的,采购单状态就是有异常
         * 2.改变该采购单每一个采购项(采购需求)状态
         *
         * 3.将成功采购的进行入库,就是库存里加上响应的数量
         */
        Long id = doneVO.getId();// 当前要改的采购单的id

        /*思路2*/
        Boolean flag = true;// 有一个采购项失败就把他变为false
        List<PurchaseItemDoneVO> items = doneVO.getItems();// 先遍历所有的采购项,分离出成功的采购项和失败的采购项

        List<PurchaseDetailEntity> updates = new ArrayList<>(10);
        for (PurchaseItemDoneVO item : items) {
            PurchaseDetailEntity detailEntity = new PurchaseDetailEntity();
            if (item.getStatus()==WareConstant.PurchaseDetailStatusEnum.HASERROR.getCode()){
                flag = false;
                detailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.HASERROR.getCode());
            }else{
                // 否则都采购成功了改他状态就可以了,并让他入库(数量相加)
                detailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.FINISH.getCode());
                /*思路3*/
                /**
                 * 每个商品都有当前商品(sku_id)给哪个仓库(ware_id),入几个(stock)  wms_ware_sku表
                 * 所以我们需要三个参数
                 */
                PurchaseDetailEntity purchaseDetailEntity = detailService.getById(item.getItemId());// 根据当前采购项的id得到采购项实体
                wareSkuService.addStock(purchaseDetailEntity.getSkuId(),purchaseDetailEntity.getWareId(),purchaseDetailEntity.getSkuNum());
            }
            detailEntity.setId(item.getItemId());
            updates.add(detailEntity);
        }
        detailService.updateBatchById(updates);
        /*思路1*/
        PurchaseEntity purchaseEntity = new PurchaseEntity();
        purchaseEntity.setId(id);
        if (flag){
            // true,那么采购单的状态是已完成
            purchaseEntity.setStatus(WareConstant.PurchaseStatusEnum.FINISH.getCode() );
        }else{
            purchaseEntity.setStatus(WareConstant.PurchaseStatusEnum.HASERROR.getCode() );
        }
        purchaseEntity.setUpdateTime(new Date());
        this.updateById(purchaseEntity);
    }

}